package cn.tedu.stx_admin.service.impl;

import cn.tedu.stx_admin.dao.cache.IAdminCacheRepository;
import cn.tedu.stx_admin.dao.persist.repository.IAdminRepository;
import cn.tedu.stx_admin.dao.persist.repository.impl.AdminRepository;
import cn.tedu.stx_admin.pojo.entity.Admin;
import cn.tedu.stx_admin.pojo.param.AdminAddNewParam;
import cn.tedu.stx_admin.pojo.param.AdminLoginParam;
import cn.tedu.stx_admin.pojo.vo.AdminLoginInfoVO;
import cn.tedu.stx_admin.pojo.vo.AdminLoginResultVO;
import cn.tedu.stx_admin.security.CustomUserDetails;
import cn.tedu.stx_admin.service.IAdminService;
import cn.tedu.stx_common.enumerator.ServiceCode;
import cn.tedu.stx_common.ex.ServiceException;
import cn.tedu.stx_common.pojo.po.AdminStatePO;
import cn.tedu.stx_common.util.JwtUtils;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;

import static cn.tedu.stx_common.consts.JwtClaimsConsts.*;

@Slf4j
@Service
public class AdminService implements IAdminService {

    @Autowired
    private IAdminRepository repository;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private IAdminCacheRepository adminCacheRepository;

    @Value("${stx.jwt.secret-key}")
    private String secretKey;
    @Value("${stx.jwt.ex-date}")
    private Long exDate;

    @Override
    public void addNew(AdminAddNewParam addNewParam) {
        String name = addNewParam.getAdminName();
        int count  =repository.countByName(name);
        if (count>0){
            String msg="名称已经被占用了!";
            throw new ServiceException(ServiceCode.ERROR_CONFLICT,msg);
        }

        Admin admin = new Admin();
        BeanUtils.copyProperties(addNewParam,admin);
        String password = passwordEncoder.encode(admin.getPassword());
        admin.setPassword(password);
        repository.insert(admin);
    }

    @Override
    public AdminLoginResultVO login(AdminLoginParam param,String userAgent,String remoteAddr) {
        // 开始处理登录验证
        log.info("Login: 进入Service阶段");
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                param.getAdminName(),param.getPassword()
        );
        log.info("认证对象：{}",authentication);
        Authentication authenticate = authenticationManager.authenticate(authentication);
        Object principal = authenticate.getPrincipal();
        CustomUserDetails userDetails= (CustomUserDetails) principal;
        log.info("认证成功后得到的userDetails:{}",userDetails);

        // 生成JWT
        AdminLoginInfoVO loginInfo=repository.getLoginVOByAdminName(userDetails.getUsername());
        Map<String,Object> claims=new HashMap<>();
        Long loginId=loginInfo.getId();
        String loginName=loginInfo.getAdminName();
        claims.put(CLAIM_USER_ID,loginId);
        claims.put(CLAIM_USER_NAME,loginName);
        claims.put(CLAIM_USER_AGENT,userAgent);
        claims.put(CLAIM_REMOTE_ADDR,remoteAddr);
        Date expiration = new Date(exDate*60L*1000);
        String jwt= JwtUtils.generate(claims,null,secretKey);
        log.info("service生成的JWT:{}",jwt);

        // 生成返回结果
        AdminLoginResultVO resultVO=new AdminLoginResultVO();
        resultVO.setId(loginId);
        resultVO.setAdminName(loginName);
        resultVO.setImgUrl(loginInfo.getImgUrl());
        List<String> permissions = loginInfo.getPermissions();
        resultVO.setPermission(permissions);
        resultVO.setToken(jwt);

        // 向Redis数据库存入用户登录数据
        AdminStatePO adminStatePO = new AdminStatePO();
        List<GrantedAuthority> authorities = new ArrayList<>();
        for (String permission : permissions) {
            authorities.add(new SimpleGrantedAuthority(permission));
        }
        String authoritiesJsonString = JSON.toJSONString(authorities);
        adminStatePO.setAuthoritiesJsonString(authoritiesJsonString);
        adminCacheRepository.saveAdminState(loginId,adminStatePO);

        return resultVO;
    }

    @Override
    public void delete(Long id) {

        int dataDelete = repository.delete(id);
        boolean cacheDelete = adminCacheRepository.delete(id);

    }


}
